#ifndef _H_SHADER
#define _H_SHADER
#include "heads.hpp"
#include "camera.hpp"
#include "sampler.hpp"
#include "geometry.hpp"
#include "scene.hpp"
#include "object.hpp"
#include "optics.hpp"
#include "camera.hpp"
#include "interaction.hpp"
#include <thread>
namespace chen {

extern unsigned __sampler_shader_pixel_count;

class Shader {
protected:
	Spectrum estimateDirectIlluminationND (
    	const SurfInteract & si, int nsamples, Sampler * samp
	) const;
public:
	const Scene * scene;
	const Camera * camera;
	int nthreads;
	Shader (const Scene * sce, const Camera * cam): scene(sce), camera(cam) {}
	virtual void render () = 0;
	inline virtual void prepare (int ntr) {nthreads = ntr; return ;}
	virtual ~Shader () {}
};
namespace SamplerShaderStatics {
	constexpr static int BLOCK_SIZE = 64;
};
class SamplerShader: public Shader {
private: 
	mutable pthread_mutex_t flock;
	mutable int lw, lh;
public:
	Sampler * sampler_f;
	int samples_per_pixel;
	inline SamplerShader (const Scene * scene, const Camera * camera, Sampler * samp, int spp):
		Shader(scene, camera), sampler_f(samp), samples_per_pixel(spp) {
			pthread_mutex_init(&flock, nullptr);
			lw = lh = 0;
		}
	virtual void render () ;
	virtual Spectrum Li (const Ray & r, Sampler * sampler) const = 0;
	void rthread (int tid) const ;
	bool fetchNext (int * w, int * h) const ;
	virtual void prepare (int ntr) ;
};

}
#endif
